const express = require('express')
const multer = require('multer')
const bcryptjs = require('bcryptjs')
const path = require('path')
const session = require('express-session')
const ws = require('ws')
let server = express()

// 引入数据库相关的model文件
const PostModel = require('./models/post')
const PostUser = require('./models/user')

//登录认证配置
server.use(
  session({
    // 选项配置
    resave: true,
    saveUninitialized: true,
    secret: 'jkjkljjljklj'
  })
)

// 上传文件设置
const upload = multer({
  dest: path.resolve(__dirname, './par')
})

// 登录认证中间件
const auth = (req, res, next) => {
  if (req.session.userInfo) {
    next()
  } else {
    res.redirect('/log')
  }
}

//req.body中间项的设置
server.use(express.json())
server.use(express.urlencoded({ extended: true }))

// ejs中间件
server.set('view engine', 'ejs')
server.set('views', path.resolve(__dirname, './views'))

//新增文章
server.post('/api/posts', async (req, res) => {
  // 1. 获取前端传递过来的参数 req.body
  console.log(req.file)
  //2. 写入数据库
  const post = new PostModel(req.body)
  try {
    const data = await post.save()
    // console.log(data)

    res.send({
      code: 1,
      msg: '写入成功'
    })
  } catch (error) {
    console.log(error)
    res.send({
      code: -1,
      msg: '写入失败'
    })
  }
})

// 查询文章
server.get('/query', async (req, res) => {
  // 1. 获取前端传递过来的参数 req.query
  // console.log(req.query)
  let title = req.query.title
  let h = parseInt(req.query.h || 1)
  let l = parseInt(req.query.l || 5)

  const posts = await PostModel.find({ title: new RegExp(title) })
    .skip((h - 1) * l)
    .limit(l)

  res.send({
    code: 0,
    data: posts
  })
})

// 删除文章
server.post('/delete', async (req, res) => {
  // 1. 取出需要删除的数
  // let posts=req.body.title
  // console.log(posts)
  // console.log(req.body)

  let bool = await PostModel.deleteOne(req.body)
  console.log(bool)

  res.send({
    code: '0',
    msg: 'ok'
  })
})

// 修改文章
server.post('/amend', async (req, res) => {
  let title1 = req.body.title1
  let title2 = req.body.title2

  await PostModel.updateOne({ title: title1 }, { title: title2 })

  res.send({
    code: '0',
    msg: '修改成功'
  })
})

// 文章列表
server.get('/index', auth, async (req, res) => {
  let y = parseInt(req.query.y) || 1
  let g = parseInt(req.query.g) || 5
  // 获取数据
  let data = await PostModel.find()
    .skip((y - 1) * g)
    .limit(g)

  // let userdata=await PostUser.find({'_id':data.userId})
  // console.log(userdata)
  // console.log(JSON.parse(data[1].user))
  //获取总条数
  let count = await PostModel.find().countDocuments()
  // 获取总页数
  let ye = Math.ceil(count / g)
  // console.log(data)
  res.render('lb', { data, ye, y })
})

//注册渲染
server.get('/reg', async (req, res) => {
  res.render('reg')
})

// 登录渲染
server.get('/log', async (req, res) => {
  res.render('log')
})

// 注册处理
server.post('/regY', async (req, res) => {
  let username = req.body.username
  let password = req.body.password

  password = await bcryptjs.hash(password, 12)

  let user = new PostUser({ username, password })

  try {
    await user.save()
    res.redirect('/log')
  } catch (error) {
    console.log(error)
    res.send({
      code: '-1',
      msg: '失败'
    })
  }
})

//登录处理
server.post('/logY', async (req, res) => {
  let username = req.body.username
  let password = req.body.password
  let bool = false
  // console.log(username)
  let user = await PostUser.findOne({ username })
  // console.log(user)
  if (user) {
    bool = await bcryptjs.compare(password, user.password)
  }

  if (bool) {
    // 用户验证通过，
    // 1. 给session上添加一些用户的信息
    req.session.userInfo = {
      userId: user._id,
      username: user.username
    }
    res.redirect('/index') //重定向
  } else {
    res.send({
      code: '-1',
      msg: '失败'
    })
  }
})

// 新增文章渲染
server.get('/create', auth, async (req, res) => {
  res.render('create')
})

// 新增文章
server.post('/createY', async (req, res) => {
  const post = await new PostModel({
    title: req.body.title,
    body: req.body.body,
    user: JSON.stringify(req.session.userInfo)
  })
  // console.log(post)
  console.log(req.file)

  try {
    const data = await post.save()
    res.redirect('/index')
  } catch (error) {
    console.log(error)
    res.send('失败')
  }
})

server.get('/ask/:title', auth, async (req, res) => {
  // console.log(req.params)
  let data = await PostModel.findOne(req.params)
  console.log(data)
  res.render('ask', { data })
})

let obj = {}

server.get('/tack', auth, (req, res) => {
  let user = JSON.stringify(req.session.userInfo)
  obj.user = req.session.userInfo
  // console.log(user)
  res.render('tack', { user })
})

// ```shell
// npm install --save bcryptjs
// ```

// 1.bcryptjs.hash(password,加强密度(1-12))
// 2.bcryptjs.compire(password,hashPassword)

// # 图片上传

// 1. 图片上传需要使用 multer 模块
// 2. 如果要做文件上传，form 表单的 enctype 属性需要设置为 multipart/form-data
// 3. 文件上传，请求方式，必须是 POST

// ## multer 模块

// 1. 安装

// ```shell
// npm install --save multer
// ```

// 2. 配置 multer

// ```js
// // 哪里要用，放哪里 routes/post.js
// const multer = require("multer");

// const upload = multer({
//   // 配置
//   dest: "临时文件的上传路径"
// });
// ```

// 3. 在具体需要用到文件上传功能的路由代码上，使用上面的 upload 对象上某个中间件函数

// ```js
// // routes/post.js

// router.post("/store", upload.single("文件的name名字"), (req, res) => {});
// ```

// 4. 做完第 3 步处理之后，在第 3 步的路由回调函数中，就可以使用 req.file 去获取到文件的信息

// 5. 后续处理

server = server.listen(8080)

const wss = new ws.Server({
  server: server
})

let index = 0
let arr = []

wss.on('connection', socket => {
  socket.username = ++index
  arr.push(socket)
  console.log(obj.user)
  arr.forEach(item => {
    if (item.username !== socket.username) {
      item.send(
        JSON.stringify({
          username: obj.user.username,
          message: `进入聊天室`
        })
      )
    }
  })

  socket.on('message', message => {
    // console.log(message);
    arr.forEach(item => {
      item.send(
        JSON.stringify({
          username: JSON.parse(message).user,
          message: JSON.parse(message).data
        })
      )
    })
  })
})
